﻿Imports WiremetModel.Entities.SupplyOrders
Imports WiremetModel.Entities
Imports WiremetModel.Specification.SupplyOrders
Imports GMap.NET
Imports GMap.NET.WindowsForms
Imports InputValidation.GeneralRules
Imports InputValidation
Imports System.ComponentModel

Public Class DieOrderInputDialog

    Private _unitOfWork As UnitOfWork
    Private _inputValidator As InputValidator

    Private _dieOrder As DieOrder
    Public Property DieOrder() As DieOrder
        Get
            Return _dieOrder
        End Get
        Set(ByVal value As DieOrder)
            _dieOrder = value
        End Set
    End Property

    Private _supplierLocationOverlay As GMapOverlay

    Public Sub New(ByRef unitOfWork As UnitOfWork)
        InitializeComponent()
        InitializeSupplierAddressMap()
        _inputValidator = New InputValidator()
        '_unitOfWork = New UnitOfWork()
        _unitOfWork = unitOfWork
        _dieOrder = New DieOrder()
        ClearErrorLabels()
        RefreshViewData()
        dtp_ExpectedDeliveryDate.MinDate = New Date(Now.Year, Now.Month, Now.Day)
    End Sub

    Public Sub New(ByRef unitOfWork As UnitOfWork, ByVal dieOrder As DieOrder)
        Me.New(unitOfWork)

        cmb_Supplier.SelectedItem = dieOrder.Supplier
        cmb_Currency.SelectedItem = dieOrder.Currency
        dtp_ExpectedDeliveryDate.MinDate = If(dieOrder.ExpectedDeliveryDate.HasValue AndAlso dieOrder.ExpectedDeliveryDate < dieOrder.SubmitDate, dieOrder.ExpectedDeliveryDate.Value, dieOrder.SubmitDate.Date)
        dtp_ExpectedDeliveryDate.Checked = dieOrder.ExpectedDeliveryDate.HasValue
        dtp_ExpectedDeliveryDate.Value = If(dieOrder.ExpectedDeliveryDate.HasValue, dieOrder.ExpectedDeliveryDate.Value, Now)
        tb_OrderNote.Text = dieOrder.Note

        Dim supplierAddress As SupplierAddress = dieOrder.Supplier.SupplierAddresses.FirstOrDefault(Function(x) x.Address.Id = dieOrder.SubmitAddress.Id)
        If Not IsNothing(supplierAddress) Then
            Dim supplierAddressIndex As Integer = lb_SupplierAddress.FindString(supplierAddress.Description)
            If Not IsNothing(supplierAddressIndex) Then
                lb_SupplierAddress.SelectedIndex = supplierAddressIndex
            End If
        Else
            lb_SupplierAddress.ClearSelected()
        End If

        gb_OrderInputData.Text = "Zamówienie: " & dieOrder.OrderNumber

        _dieOrder = dieOrder
        RefreshOrderLineTable(dieOrder.OrderLines, CType(cmb_Currency.SelectedItem, OEM.Waluta))

    End Sub

    'Private Sub DieOrderInputDialog_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
    '    _unitOfWork.Dispose()
    'End Sub

    Private Sub ClearErrorLabels()
        lbl_CurrencyError.Text = String.Empty
        lbl_SupplierError.Text = String.Empty
    End Sub

    Private Sub RefreshViewData()
        Dim supplierRepository As New Repository(Of Supplier)(_unitOfWork)
        Dim currencyRepository As New Repository(Of OEM.Waluta)(_unitOfWork)

        Dim supplierList As IEnumerable(Of Supplier) = supplierRepository.GetAll()
        Dim currencyList As IEnumerable(Of OEM.Waluta) = currencyRepository.GetAll()

        InitializeComboBox(cmb_Supplier, supplierList)
        InitializeComboBox(cmb_Currency, currencyList)

    End Sub

    Private Sub InitializeComboBox(ByRef inputComboBox As ComboBox, ByVal data As IEnumerable(Of Object))
        inputComboBox.DataSource = New BindingSource(data, Nothing)
        inputComboBox.AutoCompleteCustomSource.Clear()
        inputComboBox.AutoCompleteCustomSource.AddRange(data.Select(Function(x) x.ToString()).ToArray())
        inputComboBox.SelectedIndex = -1
    End Sub


    Private Sub InitializeSupplierAddressMap()
        GMap_SupplierAddress.MapProvider = MapProviders.GoogleMapProvider.Instance
        GMaps.Instance.Mode = AccessMode.ServerAndCache
        GMap_SupplierAddress.ForceDoubleBuffer = True
        GMap_SupplierAddress.Zoom = 8
        _supplierLocationOverlay = New GMapOverlay(GMap_SupplierAddress, "supplierLocationOverlay")
        GMap_SupplierAddress.Overlays.Add(_supplierLocationOverlay)
    End Sub


    Private Sub EnsureSupplierIsSelected()
        If IsNothing(cmb_Supplier.SelectedItem) Then
            Throw New EntityDataInputException("Proszę, wybierz dostawcę, aby kontynuować.")
        End If
    End Sub


    Private Sub cmb_Supplier_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles cmb_Supplier.SelectedIndexChanged
        Dim selectedSupplier As Supplier = CType(cmb_Supplier.SelectedItem, Supplier)
        If Not IsNothing(selectedSupplier) Then
            lb_SupplierAddress.DataSource = selectedSupplier.SupplierAddresses
        Else
            lb_SupplierAddress.DataSource = Nothing
        End If
    End Sub

    Private Function GetSelectedSupplierAddress() As SupplierAddress
        Dim selectedSupplier As Supplier = CType(cmb_Supplier.SelectedItem, Supplier)
        If Not IsNothing(selectedSupplier) Then
            Return CType(lb_SupplierAddress.SelectedValue, SupplierAddress)
        End If
        Return Nothing
    End Function

    Private Sub lb_SupplierAddress_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles lb_SupplierAddress.SelectedIndexChanged
        Dim supplierAddress As SupplierAddress = GetSelectedSupplierAddress()
        If Not IsNothing(supplierAddress) Then
            tb_SupplierAddress.Text = supplierAddress.Address.ToString()
            Dim addressLocation As New PointLatLng(supplierAddress.Address.Latitude, supplierAddress.Address.Longitude)
            Dim marker As GMapMarker = New Markers.GMapMarkerGoogleRed(addressLocation)
            _supplierLocationOverlay.Markers.Clear()
            marker.ToolTipText = supplierAddress.Supplier.CompanyName
            marker.ToolTipMode = MarkerTooltipMode.Always
            _supplierLocationOverlay.Markers.Add(marker)
            GMap_SupplierAddress.ZoomAndCenterMarkers(_supplierLocationOverlay.Id)
            GMap_SupplierAddress.Zoom = 12
        Else
            tb_SupplierAddress.Text = String.Empty
            _supplierLocationOverlay.Markers.Clear()
            GMap_SupplierAddress.ZoomAndCenterMarkers(_supplierLocationOverlay.Id)
            GMap_SupplierAddress.Zoom = 0
        End If
    End Sub




#Region "Order lines"


    Private Sub RefreshOrderLineTable(ByVal orderLineList As IEnumerable(Of DieOrderLine), ByVal currency As OEM.Waluta)
        Dim currencyToString As String = If(IsNothing(currency), String.Empty, currency.Nazwa & "/")
        dgv_DieOrderLine.Rows.Clear()
        For Each orderLine As DieOrderLine In orderLineList.OrderBy(Function(x) x.Diameter)
            Dim rowIndex As Integer = dgv_DieOrderLine.Rows.Add(
                orderLine.Id,
                orderLine.Diameter,
                "dolna: " & orderLine.DiameterToleranceMinus & "   górna: " & orderLine.DiameterTolerancePlus,
                "średnica: " & orderLine.CasingDiameter & "   wysokość: " & orderLine.CasingHeight,
                orderLine.Quantity.ToString() & " szt."
            )
            dgv_DieOrderLine.Rows(rowIndex).Tag = orderLine
        Next
        ts_lbl_TotalQuantity.Text = orderLineList.Sum(Function(x) x.Quantity).ToString() & " szt."
    End Sub


    Private Sub EnsureOrderLineIsSelected()
        If dgv_DieOrderLine.SelectedRows.Count = 0 Then
            Throw New EntityDataInputException("Proszę, wybierz pozycję zamówienia, aby kontynuować.")
        End If
    End Sub

    Private Function GetSelectedDieOrderLine() As DieOrderLine
        Return CType(dgv_DieOrderLine.SelectedRows(0).Tag, DieOrderLine)
    End Function


    Private Sub ts_btn_AddOrderLine_Click(sender As System.Object, e As System.EventArgs) Handles ts_btn_AddOrderLine.Click
        Try
            Dim dieOrderLineInputDialog As New DieOrderLineInputDialog()
            If dieOrderLineInputDialog.ShowDialog() = Windows.Forms.DialogResult.OK Then

                Dim dieOrderLine = dieOrderLineInputDialog.DieOrderLine
                dieOrderLine.DieOrder = DieOrder

                DieOrder.OrderLines.Add(dieOrderLine)
                RefreshOrderLineTable(DieOrder.OrderLines, CType(cmb_Currency.SelectedItem, OEM.Waluta))

            End If
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    Private Sub ts_btn_EditOrderLine_Click(sender As System.Object, e As System.EventArgs) Handles ts_btn_EditOrderLine.Click
        Try
            Dim selectedDieOrderLine As DieOrderLine = GetSelectedDieOrderLine()
            Dim dieOrderLineInputDialog As New DieOrderLineInputDialog(selectedDieOrderLine)
            If dieOrderLineInputDialog.ShowDialog() = Windows.Forms.DialogResult.OK Then

                selectedDieOrderLine = dieOrderLineInputDialog.DieOrderLine
                RefreshOrderLineTable(DieOrder.OrderLines, CType(cmb_Currency.SelectedItem, OEM.Waluta))

            End If
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    Private Sub ts_btn_DeleteOrderLine_Click(sender As System.Object, e As System.EventArgs) Handles ts_btn_DeleteOrderLine.Click
        Try
            Dim selectedDieOrderLine As DieOrderLine = GetSelectedDieOrderLine()
            Dim confirmationDialogResult As DialogResult = MessageBox.Show("Czy jesteś pewień?", "Uwaga", MessageBoxButtons.YesNo, MessageBoxIcon.Warning)

            If confirmationDialogResult = Windows.Forms.DialogResult.Yes Then

                DieOrder.OrderLines.Remove(selectedDieOrderLine)
                RefreshOrderLineTable(DieOrder.OrderLines, CType(cmb_Currency.SelectedItem, OEM.Waluta))

            End If
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub


#End Region



#Region "Input validation"


    Private Sub cmb_Supplier_Validating(ByVal sender As Object, ByVal e As CancelEventArgs) Handles cmb_Supplier.Validating
        Dim notNullableComboBoxValidatingSpecification As New NotNullableComboBoxValidatingSpecification(Of Supplier)
        _inputValidator.ValidateComboBox(cmb_Supplier, e, lbl_SupplierError, notNullableComboBoxValidatingSpecification)
    End Sub

    Private Sub cmb_Currency_Validating(ByVal sender As Object, ByVal e As CancelEventArgs) Handles cmb_Currency.Validating
        Dim notNullableComboBoxValidatingSpecification As New NotNullableComboBoxValidatingSpecification(Of OEM.Waluta)
        _inputValidator.ValidateComboBox(cmb_Currency, e, lbl_CurrencyError, notNullableComboBoxValidatingSpecification)
    End Sub

    Private Sub cmb_Supplier_validated(ByVal sender As Object, ByVal e As EventArgs) Handles cmb_Supplier.Validated
        lbl_SupplierError.Text = String.Empty
    End Sub

    Private Sub cmb_Currency_Validated(ByVal sender As Object, ByVal e As EventArgs) Handles cmb_Currency.Validated
        lbl_CurrencyError.Text = String.Empty
    End Sub



#End Region

    Private Sub btn_Accept_Click(sender As System.Object, e As System.EventArgs) Handles btn_Accept.Click
        Try
            If Not ValidateChildren() Then
                Throw New EntityDataInputException("Podane dane są nieprawidłowe." & vbNewLine &
                                                   "Popraw je i spróbuj ponownie.")
            End If

            If dgv_DieOrderLine.Rows.Count = 0 Then
                Throw New EntityDataInputException("Proszę, dodaj pozycje zlecenia, aby kontynuować")
            End If

            If lb_SupplierAddress.SelectedItems.Count = 0 Then
                Throw New EntityDataInputException("Proszę, wybierz adres dostawcy, aby kontynuować")
            End If


            Dim confirmationDialogResult As DialogResult = MessageBox.Show("Czy jesteś pewień?", "Uwaga!", MessageBoxButtons.YesNo, MessageBoxIcon.Warning)
            If confirmationDialogResult = Windows.Forms.DialogResult.Yes Then

                Dim dieOrderRepository As New Repository(Of DieOrder)(_unitOfWork)
                Dim dieOrderFromMonthSpecification As New OrderFromMonthSpecification(Of DieOrder)(Date.Now)
                Dim orderNumber As Integer = Now.Year * 100000 + Now.Month * 1000 + dieOrderRepository.GetAll().Where(Function(x) x.SubmitDate.Year = Now.Year AndAlso x.SubmitDate.Month = Now.Month).Count() + 1


                With DieOrder
                    .Employee = User
                    .ExpectedDeliveryDate = If(dtp_ExpectedDeliveryDate.Checked, dtp_ExpectedDeliveryDate.Value, CType(Nothing, DateTime?))
                    .Note = If(String.IsNullOrEmpty(tb_OrderNote.Text.Trim()), Nothing, tb_OrderNote.Text.Trim())
                    '.OrderNumber = CStr(Date.Now.Year * 100000 + Date.Now.Month * 1000 + dieOrderRepository.GetAllMatching(dieOrderFromMonthSpecification).Count() + 1)
                    .OrderNumber = If(String.IsNullOrEmpty(.OrderNumber), orderNumber.ToString() & "D", .OrderNumber)
                    .SubmitAddress = GetSelectedSupplierAddress().Address
                    .SubmitDate = Date.Now()
                    .Supplier = CType(cmb_Supplier.SelectedItem, Supplier)
                    .Currency = CType(cmb_Currency.SelectedItem, OEM.Waluta)
                End With

                DialogResult = Windows.Forms.DialogResult.OK
            End If
        Catch ex As EntityDataInputException
            MessageBox.Show(ex.Message, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning)
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    Private Sub btn_Cancel_Click(sender As System.Object, e As System.EventArgs) Handles btn_Cancel.Click
        DialogResult = Windows.Forms.DialogResult.Cancel
    End Sub


    Private Sub cmb_Currency_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles cmb_Currency.SelectedIndexChanged
        RefreshOrderLineTable(DieOrder.OrderLines, CType(cmb_Currency.SelectedItem, OEM.Waluta))
    End Sub

End Class